package top.lshaci.learning.springboot.rabbitmq.config;

import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.annotation.PostConstruct;

/**
 * RabbitConfig
 *
 * @author lshaci
 * @since 1.0.0
 */
@Slf4j
@Configuration
public class RabbitConfig {

    @Bean
    public Jackson2JsonMessageConverter jackson2JsonMessageConverter() {
        return new Jackson2JsonMessageConverter();
    }

    @Autowired
    private RabbitTemplate rabbitTemplate;

    @PostConstruct
    public void initRabbitTemplate() {
        // 1、服务器收到消息就回调
        //      1) spring.rabbitmq.publisher-confirm-type: correlated
        //      2) 设置确认回调 confirmCallback
        rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> {
            // correlationData 当前消息的唯一关联数据（这个消息的唯一ID）
            // ack broker是否成功收到消息
            // cause 失败的原因
            correlationData.getId();
            log.debug("消息的唯一关联数据: {}", correlationData);
            log.debug("broker是否成功收到消息: {}", ack);
            log.debug("失败的原因: {}", cause);
        });
        // 2、消息抵达队列回调（消息发送成功不会触发）
        //      1) spring.rabbitmq.publisher-returns: true   # 开启发送端消息抵达队列确认
        //      2) spring.rabbitmq.template.mandatory: true  # 只要消息抵达队列，以异步方式优先回调ReturnCallback
        //      3) 只要消息没有投递给指定队列，就触发这个回调
        rabbitTemplate.setReturnCallback((message, replyCode, replyText, exchange, routingKey) -> {
            message.getMessageProperties().getCorrelationId();
            log.debug("投递失败的消息详细信息: {}", message);
            log.debug("回复的状态码: {}", replyCode);
            log.debug("回复的文本内容: {}", replyText);
            log.debug("消息发送的交换机: {}", exchange);
            log.debug("消息发送的路由键: {}", routingKey);
        });
    }
}
